import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/screenutil.dart';

// 类似于QQ
class SlideRemoveWidget extends StatefulWidget {
  final double slideDistancePer;
  final Widget itemChild;
  final Widget slideChild;
  final double itemHeight;

  const SlideRemoveWidget({
    Key key,
    this.slideDistancePer = 0.4,
    @required this.itemChild,
    @required this.slideChild,
    @required this.itemHeight,
  }) : super(key: key);

  @override
  _SlideRemoveWidgetState createState() => _SlideRemoveWidgetState();
}

class _SlideRemoveWidgetState extends State<SlideRemoveWidget> with SingleTickerProviderStateMixin {
  final Map<Type, GestureRecognizerFactory> _gestures = <Type, GestureRecognizerFactory>{};

  double _slideMaxDistance = 0;
  double _offsetX = 0;
  AnimationController _animationController;
  Animation<double> _doubleAnimation;
  bool _isAnimationLeft = false;

  @override
  void initState() {
    _slideMaxDistance = ScreenUtil.screenWidth * widget.slideDistancePer;

    _gestures[HorizontalDragGestureRecognizer] = GestureRecognizerFactoryWithHandlers<HorizontalDragGestureRecognizer>(
      () => HorizontalDragGestureRecognizer(debugOwner: this),
      (HorizontalDragGestureRecognizer instance) {
        instance
          ..onDown = onHorizontalDragDown
          ..onUpdate = onHorizontalDragUpdate
          ..onEnd = onHorizontalDragEnd;
      },
    );

    _animationController = AnimationController(vsync: this, duration: const Duration(milliseconds: 500));
    _doubleAnimation = Tween(begin: 0.0, end: 1.0).animate(_animationController)
      ..addListener(() {
        // print(_doubleAnimation.value.toString());
        double distance = (_isAnimationLeft ? -(_slideMaxDistance + _offsetX) : -_offsetX) * _doubleAnimation.value;
        _offsetX += distance;
        setState(() {});
      })
      ..addStatusListener((status) {
        print('status == $status');
      });
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return RawGestureDetector(
      gestures: _gestures,
      child: Transform.translate(
        offset: Offset(_offsetX, 0),
        child: Container(
          height: widget.itemHeight,
          child: OverflowBox(
            alignment: Alignment.centerLeft,
            maxWidth: ScreenUtil.screenWidth * (1 + widget.slideDistancePer),
            minHeight: widget.itemHeight,
            child: Row(
              mainAxisSize: MainAxisSize.max,
              children: [
                Container(
                  child: widget.itemChild,
                  height: widget.itemHeight,
                  width: ScreenUtil.screenWidth,
                ),
                Container(
                  child: widget.slideChild,
                  height: widget.itemHeight,
                  width: _slideMaxDistance,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  void onHorizontalDragDown(DragDownDetails details) {
    print("onHorizontalDragDown, details == $details");
  }

  void onHorizontalDragUpdate(DragUpdateDetails details) {
    double offsetXDelta = details.delta.dx;
    print("onHorizontalDragUpdate, details == $details, offsetXDelta == $offsetXDelta");
    _offsetX += offsetXDelta;
    if (_offsetX <= 0 && _offsetX >= -_slideMaxDistance) {
      setState(() {});
    } else if (_offsetX > 0) {
      _offsetX = 0;
      setState(() {});
    } else if (_offsetX < -_slideMaxDistance) {
      _offsetX = -_slideMaxDistance;
      setState(() {});
    }
  }

  void onHorizontalDragEnd(DragEndDetails details) {
    print("onHorizontalDragEnd, details == $details");
    _animationController.reset();
    if (details.velocity.pixelsPerSecond.dx > 800) {
      _isAnimationLeft = false;
    } else if (details.velocity.pixelsPerSecond.dx < -800) {
      _isAnimationLeft = true;
    } else {
      if (_offsetX <= 0 && _offsetX >= -_slideMaxDistance) {
        print("end _offsetX == $_offsetX");
        _isAnimationLeft = _offsetX <= -(_slideMaxDistance / 2);
      }
    }
    _animationController.forward();
  }
}
